﻿using JsonModel;
using MySql.Data.MySqlClient;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using System.Transactions;
using static RgChannelBot.ReportCommand;
using System.Reflection;
using Google.Protobuf.WellKnownTypes;
using MySqlX.XDevAPI.Common;
using System.Diagnostics.Metrics;
using System.Xml.Linq;
using MyBot.Models;
using MyBot.Api.Types;
using MyBot.Models.Types;
using MyBot.Models.ParamModels;
using MyBot.Models.MessageModels;
using static RgChannelBot.ProfileDrawer;

namespace RgChannelBot
{
    public enum Access : byte
    {
        Channel = 1,
        PrivateMsg = 2,
        PrimaryAdmin = 4,
        SeniorAdmin = 8,
        ServerStaff = 16,
    }

    public interface ICommand
    {
        string Command { get; }
        bool AdminChannelOnly { get; }

        /// <summary>
        /// 访问类型。如果权限组等级
        /// </summary>
        int RequiredPermission { get; }

        bool BotChannelRestricted { get; }
    }
    public interface IGroupSupported
    {
        Task ChatExecute(ChatCommandInfo cmdInfo);
    }
    public interface INormalCommand : ICommand
    {
        /// <summary>
        /// 事件方法
        /// </summary>
        /// <param name="cmdInfo"></param>
        Task Execute(CommandInfo cmdInfo);
    }

    public interface IStepCommand : ICommand
    {
        /// <summary>
        /// 所有步骤执行方法
        /// </summary>
        Action<CommandInfo, CommandState>[] Actions { get; }
    }

    public class ServerQueryCommand : INormalCommand
    {
        public string Command => "/查询";

        public bool AdminChannelOnly => false;

        public int RequiredPermission => 0;

        public bool BotChannelRestricted => true;
        public async Task Execute(CommandInfo cmdInfo)
        {
            try
            {
                if (Rg.Config.Servers.Count == 0)
                {
                    await Rg.Api.GetMessageApi().SendMessageAsync(cmdInfo.ChannelId, "当前没有服务器，请联系频道主或技术人员添加服务器", passiveMsgId: cmdInfo.MessageId);
                    return;
                }
                ExecutionRequest er = new()
                {
                    Request = Request.StatusQuery
                };
                string msg = JsonConvert.SerializeObject(er);
                List<Task<string>> tasks = new();
                List<string> server_name = new();
                foreach (var con in Rg.Config.Servers)
                {
                    tasks.Add(con.SendMsg(msg));
                    server_name.Add(con.Name);
                }
                var result = (await Task.WhenAll(tasks.ToArray())).ToList();
                int id = 0;
                do
                {
                    ServerQueryDrawer sqd = new();
                    for (int i = 0; i < result.Count && i < 8; i++)
                    {
                        id++;
                        if (result[i] == "Offline" || result[i] == "Unknown")
                        {
                            sqd.AddServerNoInfo(id, server_name[id- 1], result[i] == "Offline" ? ServerQueryDrawer.NoInfo.Offline : ServerQueryDrawer.NoInfo.Unknown);
                        }
                        else
                        {
                            ServerData? sd = JsonConvert.DeserializeObject<ServerData>(result[i]);
                            if (sd == null)
                            {
                                sqd.AddServerNoInfo(id, server_name[id - 1], ServerQueryDrawer.NoInfo.Unknown);
                                continue;
                            }
                            sqd.AddServerWithInfo(id, server_name[id - 1], sd);
                        }
                    }
                    using (var s = sqd.Drawer.Surface.Snapshot())
                    {
                        using (var x = s.Encode())
                        {
                            _ = Rg.Api.GetMessageApi().SendMessageAsync(cmdInfo.ChannelId, imageData: x.ToArray(), passiveMsgId: cmdInfo.MessageId);
                        }
                    }
                    result.RemoveRange(0, Math.Min(result.Count, 8));
                }
                while (result.Count > 0);
            }
            catch (Exception e)
            {
                Log.Error(e);
            }
        }
    }

    public class AccountBindCommand : INormalCommand
    {
        public string Command => "/账号绑定";

        public bool AdminChannelOnly => false;

        public int RequiredPermission => 0;

        public bool BotChannelRestricted => true;

        public async Task Execute(CommandInfo cmdInfo)
        {
            try
            {
                if (cmdInfo.Param.Count == 0)
                {
                    await Rg.Api.GetMessageApi().SendMessageAsync(cmdInfo.ChannelId, "使用方法：/账号绑定 [Steam64位ID]", referenceMessageId: cmdInfo.MessageId,
                        passiveMsgId: cmdInfo.MessageId);
                    return;
                }
                MySqlConnection con = new(Rg.ConnectionString);
                con.Open();
                MySqlCommand cmd = new($"UPDATE `cdcp_player_data` SET `channel_id` = '{cmdInfo.Sender.Id}' WHERE `userid` = '{cmdInfo.Param.First()}@steam'", con);
                int result = cmd.ExecuteNonQuery();
                con.Close();
                if (result == 0)
                {
                    await Rg.Api.GetMessageApi().SendMessageAsync(cmdInfo.ChannelId, "绑定失败！数据库中没有找到指定角色", referenceMessageId: cmdInfo.MessageId,
        passiveMsgId: cmdInfo.MessageId);
                    return;
                }
                await Rg.Api.GetMessageApi().SendMessageAsync(cmdInfo.ChannelId, "绑定成功！", passiveMsgId: cmdInfo.MessageId);
                await Rg.Api.GetMessageApi().RetractMessageAsync(cmdInfo.ChannelId, cmdInfo.MessageId, true);
                return;
            }
            catch (Exception e)
            {
                Log.Error(e);
            }
        }
    }

    public class ProfileCommand : INormalCommand
    {
        public string Command => "/个人信息";

        public bool AdminChannelOnly => false;

        public int RequiredPermission => 0;
        public bool BotChannelRestricted => true;

        public static async Task<PlayerData?> GetPlayerDataAsync(string id, bool channel)
        {
            MySqlConnection con = new(Rg.ConnectionString);
            await con.OpenAsync();
            PlayerData? pd = null;
            MySqlCommand cmd = new($"SELECT * FROM `cdcp_player_data` WHERE `{(channel ? "channel_id" : "userid")}` = '{id}'", con);
            using (MySqlDataReader reader = cmd.ExecuteReader())
            {
                if (reader.Read())
                {
                    pd = new PlayerData()
                    {
                        Nickname = reader.GetString("nickname"),
                        UserId = reader.GetString("userid"),
                        Level = reader.GetInt32("level"),
                        Points = reader.GetInt32("points"),
                        Experience = reader.GetInt32("exp"),
                        Mvp = reader.GetInt32("mvp"),
                        LastLogin = reader.GetDateTime("lastlogin")
                    };
                    reader.Close();
                }
                else
                {
                    reader.Close();
                    await con.CloseAsync();
                    return pd;
                }
            }
            cmd = new MySqlCommand($"SELECT * FROM `cdcp_badge` WHERE `userid`='{pd.UserId}'", con);
            using (MySqlDataReader reader = cmd.ExecuteReader())
            {
                if (reader.Read())
                {
                    pd.DonatorBadge = new Badge()
                    {
                        Text = reader.GetString("badge"),
                        Color = reader.GetString("color")
                    };
                }
                reader.Close();
            }
            cmd = new MySqlCommand($"SELECT * FROM `cdcp_badge_special` WHERE `userid`='{pd.UserId}'", con);
            using (MySqlDataReader reader = cmd.ExecuteReader())
            {
                List<Badge> badges = new List<Badge>();
                while (reader.Read())
                {
                    badges.Add(new Badge()
                    {
                        Text = reader.GetString("badge"),
                        Color = reader.GetString("color")
                    });
                }
                pd.SpecialBadges = badges.ToArray();
                reader.Close();
            }
            cmd = new MySqlCommand($"SELECT * FROM `cdcp_custom_message` WHERE `userid`='{pd.UserId}'", con);
            using (MySqlDataReader reader = cmd.ExecuteReader())
            {
                if (reader.Read())
                {
                    pd.JoinMessage = new(reader.GetString("content"), reader.GetDateTime("expires"));
                }
                reader.Close();
            }
            cmd = new MySqlCommand($"SELECT * FROM `cdcp_rainbow` WHERE `userid`='{pd.UserId}'", con);
            using (MySqlDataReader reader = cmd.ExecuteReader())
            {
                if (reader.Read())
                {
                    pd.RainbowBadge = reader.GetDateTime("expires");
                }
                reader.Close();
            }
            cmd = new MySqlCommand($"SELECT * FROM `cdcp_mvp_music` WHERE `userid`='{pd.UserId}'", con);
            using (MySqlDataReader reader = cmd.ExecuteReader())
            {
                if (reader.Read())
                {
                    string[] array = reader.GetString("url").Split('/');
                    pd.MvpMusic = new KeyValuePair<string, DateTime>(array.Last(), reader.GetDateTime("expires"));
                }
                reader.Close();
            }
            cmd = new MySqlCommand($"SELECT * FROM `cdcp_reversed_slot` WHERE `userid`='{pd.UserId}'", con);
            using (MySqlDataReader reader = cmd.ExecuteReader())
            {
                if (reader.Read())
                {
                    pd.Reservation = reader.GetDateTime("expires");
                }
                reader.Close();
            }
            await con.CloseAsync();
            return pd;
        }

        public async Task Execute(CommandInfo cmdInfo)
        {
            try
            {
                await Rg.Api.GetReactionApi().AddReactionAsync(cmdInfo.ChannelId, cmdInfo.MessageId, new Emoji() { Id = "128076", Type = 2 });
                MySqlConnection con = new(Rg.ConnectionString);
                await con.OpenAsync();
                PlayerData? pd = await GetPlayerDataAsync(cmdInfo.Sender.Id, true);
                if (pd == null)
                {
                    await Rg.Api.GetMessageApi().SendMessageAsync(cmdInfo.ChannelId, "你还没有绑定游戏账户！请使用指令：/账号绑定 [Steam64位ID] 来绑定，如果遇到错绑或为Discord账户，请联系技术组",
    referenceMessageId: cmdInfo.MessageId, passiveMsgId: cmdInfo.MessageId);
                    return;
                }
                ExecutionRequest req = new()
                {
                    Request = Request.PlayerInformation
                };
                req.Parameters.Add("userid", pd.UserId);
                List<Task<string>> tasks = new();
                string msg = JsonConvert.SerializeObject(req);
                foreach (var conn in Rg.Config.Servers)
                {
                    tasks.Add(conn.SendMsg(msg));
                }
                var result = await Task.WhenAll(tasks.ToArray());
                int server = 0;
                for (int i = 0; i < result.Length; i++)
                {
                    if (result[i] == "Offline" || result[i] == "Unknown")
                        continue;
                    ExecutionResponse? rep = JsonConvert.DeserializeObject<ExecutionResponse>(result[i]);
                    if (rep != null && rep.Success)
                    {
                        pd.OnlineData = JsonConvert.DeserializeObject<OnlineData>((string)rep.Response["data"]);
                        server = i + 1;
                        break;
                    }
                }
                await Rg.Api.GetMessageApi().SendMessageAsync(cmdInfo.ChannelId, imageData: await ProfileDrawer.Draw(pd, server),
        referenceMessageId: cmdInfo.MessageId, passiveMsgId: cmdInfo.MessageId);
            }
            catch (Exception e)
            {
                Log.Error(e);
            }
        }
    }

    public class PlayerCommand : INormalCommand
    {
        public string Command => "/player";

        public bool AdminChannelOnly => true;

        public int RequiredPermission => 1;

        public bool BotChannelRestricted => true;

        public async Task Execute(CommandInfo cmdInfo)
        {
            if (cmdInfo.Param.Count == 0 || (cmdInfo.Param.Count == 1 && int.TryParse(cmdInfo.Param[0], out _)))
            {
                await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
    "用法：/player [服务器编号] <ID(如果填写了服务器编号)/SteamID>", cmdInfo.MessageId);
                return;
            }
            ExecutionRequest er = new()
            {
                Request = Request.PlayerInformation
            };
            er.Parameters.Add("userid", cmdInfo.Param[^1]);
            bool id_search = int.TryParse(cmdInfo.Param[^1], out _);
            int server = 0;
            PlayerData? pd = null;
            if (!id_search)
            {
                pd = await ProfileCommand.GetPlayerDataAsync(cmdInfo.Param[^1].ToString(), false);
                if (pd == null)
                {
                    await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
"❌数据库中未找到该玩家，请检查用户ID是否正确", cmdInfo.MessageId);
                    return;
                }
            }
            string msg = JsonConvert.SerializeObject(er);
            bool specified = cmdInfo.Param.Count >= 2;
            bool suc = false;
            List<Task<string>> tasks = new();
            if (specified)
            {
                if (!int.TryParse(cmdInfo.Param[0], out int id))
                {
                    await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
                    "请输入正确的服务器编号", cmdInfo.MessageId);
                    return;
                }
                if (id > Rg.Config.Servers.Count)
                {
                    await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
                    "你要不要看看你有几个服务器", cmdInfo.MessageId);
                    return;
                }
                server = id;
                tasks.Add(Rg.Config.Servers[id - 1].SendMsg(msg));
            }
            else
            {
                Rg.Config.Servers.ForEach(x => tasks.Add(x.SendMsg(msg)));
            }
            var result = await Task.WhenAll(tasks.ToArray());
            for (int i = 0; i < result.Length; i++)
            {
                try
                {
                    if (result[i] == "Offline" || result[i] == "Unknown")
                    {
                        continue;
                    }
                    else
                    {
                        ExecutionResponse? rep = JsonConvert.DeserializeObject<ExecutionResponse>(result[i]);
                        if (rep != null && rep.Success)
                        {
                            var online = JsonConvert.DeserializeObject<OnlineData>((string)rep.Response["data"]);
                            if (online != null)
                            {
                                pd ??= await ProfileCommand.GetPlayerDataAsync(online.UserId, false);
                                if (pd != null)
                                {
                                    pd.OnlineData = online;
                                    if (!specified)
                                        server = i + 1;
                                    suc = true;
                                    break;
                                }
                                else
                                {
                                    await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
"❌出现了内部错误，无法查询该档案，请联系技术组", cmdInfo.MessageId);
                                    return;
                                }
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    Log.Error(e);
                    continue;
                }
            }
            if (!suc && specified)
            {
                await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
$"未能找到指定玩家，玩家可能不在当前服务器内", cmdInfo.MessageId);
                return;
            }
            if (pd == null)
            {
                await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
"❌出现了内部错误，无法查询该档案，请联系技术组", cmdInfo.MessageId);
                return;
            }
            byte[] png = await ProfileDrawer.Draw(pd, server, false);
            await Rg.Api.GetMessageApi().SendMessageAsync(cmdInfo.ChannelId, imageData: png, passiveMsgId: cmdInfo.MessageId);
        }
    }

    public class EditColorCommand : INormalCommand
    {
        public string Command => "/身份组改色";

        public bool AdminChannelOnly => false;

        public int RequiredPermission => 5;
        public bool BotChannelRestricted => false;

        public async Task Execute(CommandInfo cmdInfo)
        {
            if (cmdInfo.Param.Count < 2)
            {
                await Rg.Api.GetMessageApi().SendMessageAsync(cmdInfo.ChannelId, "使用方法：/身份组改色 [名字] [HEX(带#)]", referenceMessageId: cmdInfo.MessageId,
                    passiveMsgId: cmdInfo.MessageId);
                return;
            }
            var list = (await Rg.Api.GetChannelRoleApi().GetRolesAsync(Rg.Config.GuildId)).Roles.FirstOrDefault(x => x.Name == cmdInfo.Param[0]);
            if (list == null)
            {
                await Rg.Api.GetMessageApi().SendMessageAsync(cmdInfo.ChannelId, "未找到对应身份组！请检查名字", referenceMessageId: cmdInfo.MessageId,
    passiveMsgId: cmdInfo.MessageId);
                return;
            }
            try
            {
                await Rg.Api.GetChannelRoleApi().UpdateInfoAsync(new RoleInfo()
                {
                    Name = cmdInfo.Param[0],
                    Color = cmdInfo.Param[1],
                    Hoist = list.Hoist
                }, Rg.Config.GuildId, list.Id);
            }
            catch (Exception e)
            {
                Log.Error(e.ToString());
                await Rg.Api.GetMessageApi().SendMessageAsync(cmdInfo.ChannelId, "更改失败！请检查该身份组是否可改，HEX值是否正确", referenceMessageId: cmdInfo.MessageId,
    passiveMsgId: cmdInfo.MessageId);
                return;
            }
            await Rg.Api.GetMessageApi().SendMessageAsync(cmdInfo.ChannelId, "改色成功！", referenceMessageId: cmdInfo.MessageId,
passiveMsgId: cmdInfo.MessageId);
        }
    }

    public class SignInCommand : INormalCommand
    {
        public string Command => "/打卡";

        public bool AdminChannelOnly => false;

        public int RequiredPermission => 0;
        public bool BotChannelRestricted => true;

        public async Task Execute(CommandInfo cmdInfo)
        {
            try
            {
                MySqlConnection con = new(Rg.ConnectionString);
                con.Open();
                string userid = "";
                DateTime last = DateTime.MinValue;
                DateTime sign = DateTime.MinValue;
                int amount = new Random().Next(1, 11);
                MySqlCommand cmd = new($"SELECT * FROM `cdcp_player_data` WHERE `channel_id` = '{cmdInfo.Sender.Id}'", con);
                using (MySqlDataReader reader = cmd.ExecuteReader())
                {
                    if (reader.Read())
                    {
                        userid = reader.GetString("userid");
                        last = reader.GetDateTime("lastqqsign");
                        sign = reader.GetDateTime("lastlogin");
                        reader.Close();
                    }
                    else
                    {
                        await Rg.Api.GetMessageApi().SendMessageAsync(cmdInfo.ChannelId, "你还没有绑定游戏账户！请使用指令：/账号绑定 [Steam64位ID] 来绑定，如果遇到错绑或为Discord账户，请联系技术组",
                            referenceMessageId: cmdInfo.MessageId, passiveMsgId: cmdInfo.MessageId);
                        reader.Close();
                        con.Close();
                        return;
                    }
                }
                if (sign.Date != DateTime.Now.Date)
                {
                    await Rg.Api.GetMessageApi().SendMessageAsync(cmdInfo.ChannelId,
    "今天还没有上线哦",
referenceMessageId: cmdInfo.MessageId, passiveMsgId: cmdInfo.MessageId);
                    return;
                }
                if (last.Date == DateTime.Now.Date)
                {
                    await Rg.Api.GetMessageApi().SendMessageAsync(cmdInfo.ChannelId,
                        "你今天已经打过卡了！",
        referenceMessageId: cmdInfo.MessageId, passiveMsgId: cmdInfo.MessageId);
                    return;
                }
                ExecutionRequest er = new ExecutionRequest()
                {
                    Request = Request.SignIn
                };
                er.Parameters.Add("userid", userid);
                er.Parameters.Add("amount", amount);
                string msg = JsonConvert.SerializeObject(er);
                List<Task<string>> tasks = new();
                foreach (var conn in Rg.Config.Servers)
                {
                    tasks.Add(conn.SendMsg(msg));
                }
                var result = await Task.WhenAll(tasks.ToArray());
                for (int i = 0; i < result.Length; i++)
                {
                    if (result[i] != "Offline" && result[i] != "Unknown")
                    {
                        ExecutionResponse? rep = JsonConvert.DeserializeObject<ExecutionResponse>(result[i]);
                        if (rep != null && rep.Success)
                        {
                            await Rg.Api.GetMessageApi().SendMessageAsync(cmdInfo.ChannelId,
        $"打卡成功！积分：+{amount}",
    referenceMessageId: cmdInfo.MessageId, passiveMsgId: cmdInfo.MessageId);
                            break;
                        }
                    }
                }
                cmd = new($"UPDATE `cdcp_player_data` SET `points` = `points` + '{amount}', `lastqqsign` = '{DateTime.Now:yyyy-MM-dd}' WHERE `userid` = '{userid}'", con);
                int re = cmd.ExecuteNonQuery();
                con.Close();
                await Rg.Api.GetMessageApi().SendMessageAsync(cmdInfo.ChannelId,
    $"打卡成功！{(re == 0 ? "大概？" : $"积分：+{amount}")}",
    referenceMessageId: cmdInfo.MessageId, passiveMsgId: cmdInfo.MessageId);
            }
            catch (Exception e)
            {
                Log.Error(e);
            }
        }
    }

    public class CloseCommand : INormalCommand
    {
        public string Command => "/结束会话";

        public bool AdminChannelOnly => false;

        public int RequiredPermission => 0;
        public bool BotChannelRestricted => false;

        public async Task Execute(CommandInfo cmdInfo)
        {
            var index = Tickets.FindIndex(x => x.Channel == cmdInfo.ChannelId);
            if (index != -1)
            {
                Ticket ticket = Tickets[index];
                if (ticket.Closed)
                {
                    await Close(ticket, false, cmdInfo.MessageId);
                }
                else
                {
                    await Close(ticket, ticket.Issuer.Id == cmdInfo.Sender.Id, cmdInfo.MessageId);
                }
            }
        }
    }

    public class ReportCommand : INormalCommand
    {
        public string Command => "/发起工单";

        public bool AdminChannelOnly => false;

        public int RequiredPermission => 0;
        public bool BotChannelRestricted => false;

        public static List<Ticket> Tickets = new();
        private static bool _enabled = true;

        public static bool Enabled
        {
            get => _enabled;
            set
            {
                _enabled = value;
                if (!value)
                {
                    Tickets.ForEach(x => Close(x, true, ""));
                }
            }
        }

        public static async Task Close(Ticket t, bool client, string messageId)
        {
            if (client)
            {
                try
                {
                    await Rg.Api.GetChannelPermissionApi().UpdatePermissionsAsync(t.Channel, t.Issuer.Id, remove: ChannelPermissionType.Message | ChannelPermissionType.Check);
                }
                catch { }
                await Rg.Api.GetChannelApi().UpdateChannelNameAsync(t.Channel, $"[🔶] - {t.Id}");
                t.Closed = true;
                int index = Tickets.FindIndex(x => x.Id == t.Id);
                if (index != -1)
                {
                    Tickets[index] = t;
                    await Rg.Api.GetMessageApi().SendMessageAsync(t.Channel, "玩家已关闭会话，收集完证据且不再需要该工单时，请输入【/结束会话】删除该子频道", passiveMsgId: messageId);
                }
            }
            else
            {
                Tickets.Remove(t);
                await Rg.Api.GetChannelApi().DeleteChannelAsync(t.Channel);
            }
        }

        public struct Ticket
        {
            public readonly string Id;
            public readonly User Issuer;
            public readonly string Channel;
            public bool Closed;

            public void SetClosed()
            {
                Closed = true;
            }

            public Ticket(string id, User issuer, string channel)
            {
                Id = id;
                Issuer = issuer;
                Channel = channel;
                Closed = false;
            }
        }

        public async Task Execute(CommandInfo cmdInfo)
        {
            if (Tickets.Any(x => x.Issuer.Id == cmdInfo.Sender.Id))
            {
                await Rg.Api.GetMessageApi().SendMessageAsync(cmdInfo.ChannelId, "当前有一个工单未被关闭，在开启新会话前请关闭或者等待管理员关闭",
                    referenceMessageId: cmdInfo.MessageId, passiveMsgId: cmdInfo.MessageId);
                return;
            }
            int code = new Random().Next(100, 1000);
            var admins = (from x in (await Rg.Api.GetMemberApi().GetAllMembersAsync(Rg.Config.GuildId))
                          where x.Roles.Intersect(Rg.Config.GroupPermissions.Keys).Any()
                          select x.User.Id).ToList();
            Channel channel = await Rg.Api.GetChannelApi().CreateChannelAsync(Rg.Config.GuildId, new Channel()
            {
                GuildId = Rg.Config.GuildId,
                Name = $"[🔷] - {code}",
                Type = ChannelType.Text,
                ParentId = cmdInfo.GuildId == Rg.Config.GuildId ? Rg.Config.TicketGroupId : "0",
                PrivateType = ChannelPrivateType.AdminAndSpecifiedMembers,
                PrivateUserIds = new List<string>(),
                SpeakPermission = ChannelSpeakPermission.Everyone,
                SubType = ChannelSubType.IdleChat
            });
            foreach (var role in Rg.Config.GroupPermissions.Where(x => x.Value > 0))
            {
                try
                {
                    await Rg.Api.GetChannelPermissionApi().UpdateRolePermissionAsync(channel.Id, role.Key, ChannelPermissionType.Message | ChannelPermissionType.Check);
                }
                catch
                {
                    continue;
                }
            }
            Rg.Api.GetChannelPermissionApi().UpdatePermissionsAsync(channel.Id, cmdInfo.Sender.Id, ChannelPermissionType.Message | ChannelPermissionType.Check);
            Tickets.Add(new Ticket(code.ToString(), cmdInfo.Sender, channel.Id));
            await Rg.Api.GetMessageApi().SendMessageAsync(cmdInfo.ChannelId, $"已创建会话！【<#{channel.Id}>】←点击进入",
    referenceMessageId: cmdInfo.MessageId, passiveMsgId: cmdInfo.MessageId);
            await Rg.Api.GetMessageApi().SendMessageAsync(channel.Id,
                $"<@!{cmdInfo.Sender.Id}> 工单已创建。 用户会话结束后请输入【/结束会话】来单方面关闭会话。" +
                $"管理员一方在收集证据完毕后可再次输入来删除该工单", passiveMsgId: cmdInfo.MessageId);
        }
    }

    public class CmdCommand : INormalCommand
    {
        public string Command => "/cmd";

        public bool AdminChannelOnly => true;

        public int RequiredPermission => 4;

        public bool BotChannelRestricted => true;

        public async Task Execute(CommandInfo cmdInfo)
        {
            if (cmdInfo.Param.Count < 2)
            {
                await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
    "用法：/cmd <服务器编号(*代表全部)或用逗号分隔> <指令>", cmdInfo.MessageId);
                return;
            }
            List<int> indexs = new();
            if (cmdInfo.Param[0] == "*")
            {
                for (int i = 0; i < Rg.Config.Servers.Count; i++)
                    indexs.Add(i);
            }
            else
            {
                string[] array = cmdInfo.Param[0].Split(',', StringSplitOptions.RemoveEmptyEntries);
                foreach (string s in array)
                {
                    if (!int.TryParse(s, out int id))
                    {
                        await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
                            "服务器编号中含有非法字符", cmdInfo.MessageId);
                        return;
                    }
                    indexs.Add(id - 1);
                }
            }
            string cmd = "";
            for (int i = 1; i < cmdInfo.Param.Count; i++)
                cmd += cmdInfo.Param[i] + " ";
            cmd = cmd.TrimEnd();
            ExecutionRequest er = new()
            {
                Request = Request.CommandExecute
            };
            er.Parameters.Add("cmd", cmd);
            string msg = JsonConvert.SerializeObject(er);
            foreach (var index in indexs)
            {
                try
                {
                    if (index >= Rg.Config.Servers.Count)
                        continue;
                    var server = Rg.Config.Servers[index];
                    string result = await server.SendMsg(msg);
                    if (result == "Offline" || result == "Unknown")
                    {
                        await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
                             $"【#{index + 1} 服务器】离线", cmdInfo.MessageId);
                        continue;
                    }
                    ExecutionResponse? rep = JsonConvert.DeserializeObject<ExecutionResponse>(result);
                    if (rep == null)
                    {
                        await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
                              $"【#{index + 1} 服务器】发出了未知的回应", cmdInfo.MessageId);
                        continue;
                    }
                    await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
         $"【#{index + 1} 服务器 | {(rep.Success ? "✅" : "❌")}】\n{rep.Response["response"]}", cmdInfo.MessageId);
                }
                catch (Exception e)
                {
                    Log.Error(e);
                    continue;
                }
            }
        }
    }

    public class BanCommand : INormalCommand
    {
        public string Command => "/ban";

        public bool AdminChannelOnly => true;

        public int RequiredPermission => 2;

        public bool BotChannelRestricted => true;

        public async Task Execute(CommandInfo cmdInfo)
        {
            if (cmdInfo.Param.Count < 3)
            {
                await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
    "用法：/ban [服务器编号(如果执行SteamID封禁，可以不填)] <SteamID/数字ID> <时长> <原因>" +
    "【时长填写格式：纯数字默认单位为分，以h/H结尾为小时, d/D为天，m/M为月(30天), y/Y为年（不可复合）】", cmdInfo.MessageId);
                return;
            }
            ExecutionRequest er = new()
            {
                Request = Request.Ban
            };
            bool specified = cmdInfo.Param.Count == 4;
            if (!int.TryParse(cmdInfo.Param[specified ? 2 : 1], out int duration))
            {
                if (!int.TryParse(cmdInfo.Param[specified ? 2 : 1].Remove(cmdInfo.Param[specified ? 2 : 1].Length - 1, 1), out duration))
                {
                    await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
                    "请输入正确的时长", cmdInfo.MessageId);
                    return;
                }
                switch (cmdInfo.Param[specified ? 2 : 1].Last().ToString().ToLower())
                {
                    case "h": duration *= 60; break;
                    case "d": duration *= 1440; break;
                    case "m": duration *= 43200; break;
                    case "y": duration *= 525960; break;
                    default:
                        {
                            await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
                            "请输入正确的时长单位", cmdInfo.MessageId);
                            return;
                        }
                }
            }
            er.Parameters.Add("userid", cmdInfo.Param[specified ? 1 : 0]);
            er.Parameters.Add("duration", duration);
            er.Parameters.Add("reason", cmdInfo.Param[specified ? 3 : 2]);
            er.Parameters.Add("specified", specified);
            string msg = JsonConvert.SerializeObject(er);
            List<Task<string>> tasks = new();
            if (specified)
            {
                if (!int.TryParse(cmdInfo.Param[0], out int id))
                {
                    await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
                    "请输入正确的服务器编号", cmdInfo.MessageId);
                    return;
                }
                if (id > Rg.Config.Servers.Count)
                {
                    await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
                    "你要不要看看你有几个服务器", cmdInfo.MessageId);
                    return;
                }
                tasks.Add(Rg.Config.Servers[id - 1].SendMsg(msg));
            }
            else
            {
                Rg.Config.Servers.ForEach(x => tasks.Add(x.SendMsg(msg)));
            }
            var result = await Task.WhenAll(tasks.ToArray());
            for (int i = 0; i < result.Length; i++)
            {
                try
                {
                    if (result[i] == "Offline" || result[i] == "Unknown")
                    {
                        continue;
                    }
                    else
                    {
                        ExecutionResponse? rep = JsonConvert.DeserializeObject<ExecutionResponse>(result[i]);
                        if (rep == null)
                        {
                            continue;
                        }
                        if (rep.Success)
                        {
                            string nickname = (string)rep.Response["nickname"];
                            string userid = (string)rep.Response["userid"];
                            await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
                                $"成功！玩家【{nickname}】({userid}) 已被封禁 {Extensions.FormatTime(duration)}", cmdInfo.MessageId);
                            MySqlConnection con = new(Rg.ConnectionString);
                            await con.OpenAsync();
                            MySqlCommand cmd = new
                                ($"INSERT INTO violation(id, violation_description, violation_datetime, duration, issuer) values('{userid}', '{er.Parameters["reason"]}', '{DateTime.Now:yyyy-MM-dd HH:mm:ss}', {duration}, '{cmdInfo.Sender.UserName}');", con);
                            await cmd.ExecuteNonQueryAsync();
                            await con.CloseAsync();
                            return;
                        }
                    }
                }
                catch (Exception e)
                {
                    Log.Error(e);
                    continue;
                }
            }
            if (specified)
            {
                await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
$"封禁失败！可能是指定ID对应玩家不存在", cmdInfo.MessageId);
            }
            else
            {
                er.Parameters["specified"] = true;
                msg = JsonConvert.SerializeObject(er);
                foreach (var svr in Rg.Config.Servers)
                {
                    string rsu = await svr.SendMsg(msg);
                    try
                    {
                        if (rsu == "Offline" || rsu == "Unknown")
                        {
                            continue;
                        }
                        else
                        {
                            ExecutionResponse? rep = JsonConvert.DeserializeObject<ExecutionResponse>(rsu);
                            if (rep == null)
                            {
                                continue;
                            }
                            if (rep.Success)
                            {
                                string nickname = (string)rep.Response["nickname"];
                                string userid = (string)rep.Response["userid"];
                                await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
                                    $"成功！玩家【{nickname}】({userid}) 已被封禁 {Extensions.FormatTime(duration)}", cmdInfo.MessageId);
                                MySqlConnection con = new(Rg.ConnectionString);
                                await con.OpenAsync();
                                MySqlCommand cmd = new
                                    ($"INSERT INTO violation(id, violation_description, violation_datetime, duration, issuer) values('{userid}', '{er.Parameters["reason"]}', '{DateTime.Now:yyyy-MM-dd HH:mm:ss}', {duration}, '{cmdInfo.Sender.UserName}');", con);
                                await cmd.ExecuteNonQueryAsync();
                                await con.CloseAsync();
                                return;
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        Log.Error(e);
                        continue;
                    }
                }
                await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
$"封禁失败！没有任何服务器返回一个离线封禁！", cmdInfo.MessageId);
            }
        }
    }

    public class RecordComand : INormalCommand
    {
        public string Command => "/违规记录";

        public bool AdminChannelOnly => true;

        public int RequiredPermission => 2;

        public bool BotChannelRestricted => true;

        public async Task Execute(CommandInfo cmdInfo)
        {
            if (cmdInfo.Param.Count < 3)
            {
                await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
"用法：/违规记录 <SteamID> <时长> <违规描述>" +
"【时长填写格式：纯数字默认单位为分，以h/H结尾为小时, d/D为天，m/M为月(30天), y/Y为年（不可复合）】", cmdInfo.MessageId);
                return;
            }
            if (!int.TryParse(cmdInfo.Param[1], out int duration))
            {
                if (!int.TryParse(cmdInfo.Param[1].Remove(cmdInfo.Param[1].Length - 1, 1), out duration))
                {
                    await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
                    "请输入正确的时长", cmdInfo.MessageId);
                    return;
                }
                switch (cmdInfo.Param[1].Last().ToString().ToLower())
                {
                    case "h": duration *= 60; break;
                    case "d": duration *= 1440; break;
                    case "m": duration *= 43200; break;
                    case "y": duration *= 525960; break;
                    default:
                        {
                            await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
                            "请输入正确的时长单位", cmdInfo.MessageId);
                            return;
                        }
                }
            }
            string userid = cmdInfo.Param[0];
            string desc = cmdInfo.Param[2];
            MySqlConnection con = new(Rg.ConnectionString);
            await con.OpenAsync();
            MySqlCommand cmd = new
                ($"INSERT INTO violation(id, violation_description, violation_datetime, duration, issuer) values('{userid}', '{desc}', '{DateTime.Now:yyyy-MM-dd HH:mm:ss}', {duration}, '{cmdInfo.Sender.UserName}');", con);
            await cmd.ExecuteNonQueryAsync();
            await con.CloseAsync();
            await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
                "已记录违规", cmdInfo.MessageId);
            return;
        }
    }

    public class RecentViolationCommand : INormalCommand
    {
        public string Command => "/最近违规";

        public bool AdminChannelOnly => true;

        public int RequiredPermission => 1;

        public bool BotChannelRestricted => true;

        public struct Violation
        {
            public string violation_description;
            public int duration;
            public string violation_datetime;
            public string issuer;
            public string id;
            public int refid;
        }

        public async Task Execute(CommandInfo cmdInfo)
        {
            MySqlConnection connection = new(Rg.ConnectionString);
            await connection.OpenAsync();
            List<Violation> violations = new List<Violation>();
            string query = "SELECT * FROM violation ORDER BY violation_datetime DESC LIMIT 5;";
            MySqlCommand cmd = new(query, connection);
            MySqlDataReader reader = cmd.ExecuteReader();
            while (reader.Read())
            {
                Violation violation = new();
                violation.violation_description = Convert.ToString(reader["violation_description"]);
                violation.duration = Convert.ToInt32(reader["duration"]);
                violation.violation_datetime = Convert.ToString(reader["violation_datetime"]);
                violation.issuer = Convert.ToString(reader["issuer"]);
                violation.id = Convert.ToString(reader["id"]);
                violations.Add(violation);
            }
            reader.Close();
            await connection.CloseAsync();
            connection.Dispose();
            string history = "";
            for (int i = 0; i < violations.Count; i++)
            {
                history += Environment.NewLine + (i + 1).ToString() + ". " + "用户ID：" + violations.ElementAt(i).id + Environment.NewLine + "违规原因：" + violations.ElementAt(i).violation_description + Environment.NewLine + "封禁时长：" + Extensions.FormatTime(violations.ElementAt(i).duration) + Environment.NewLine + "违规时间：" + violations.ElementAt(i).violation_datetime + Environment.NewLine + "处理人：" + violations.ElementAt(i).issuer;
            }
            await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
    "最近违规：" + history, cmdInfo.MessageId);
        }
    }

    public class PlayerViolationCommand : INormalCommand
    {
        public string Command => "/违规查询";

        public bool AdminChannelOnly => true;

        public int RequiredPermission => 1;

        public bool BotChannelRestricted => true;

        public struct Violation
        {
            public string violation_description;
            public int duration;
            public string violation_datetime;
            public string issuer;
            public string id;
            public int refid;
        }

        public async Task Execute(CommandInfo cmdInfo)
        {
            if (cmdInfo.Param.Count == 0)
            {
                await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
    "用法：/违规查询 <用户ID>", cmdInfo.MessageId);
                return;
            }
            string id = cmdInfo.Param[0];
            if (!id.Contains("@steam") && !id.Contains("@discord"))
            {
                id += "@steam";
            }
            List<Violation> violations = new List<Violation>();
            string query = $"SELECT * FROM violation where id = '{id}'";
            MySqlConnection connection = new(Rg.ConnectionString);
            await connection.OpenAsync();
            MySqlCommand cmd = new(query, connection);
            using (MySqlDataReader reader = cmd.ExecuteReader())
            {
                while (reader.Read())
                {
                    Violation violation = new Violation
                    {
                        violation_description = Convert.ToString(reader["violation_description"]),
                        duration = Convert.ToInt32(reader["duration"]),
                        violation_datetime = Convert.ToString(reader["violation_datetime"]),
                        issuer = Convert.ToString(reader["issuer"]),
                        refid = Convert.ToInt32(reader["refid"])
                    };
                    violations.Add(violation);
                }
                reader.Close();
            }
            await connection.CloseAsync();
            connection.Dispose();
            string result = "无违规记录";
            if (violations.Count != 0)
            {
                StringBuilder resultString = new StringBuilder($"已有违规次数{violations.Count}次，上次违规在{violations.Last().violation_datetime}，封禁时长{Extensions.FormatTime(violations.Last().duration)}。\n历史违规：\n");
                for (int i = 0; i < violations.Count; i++)
                {
                    resultString.Append(Environment.NewLine + (i + 1).ToString() + ". " + "违规原因：" + violations.ElementAt(i).violation_description +
                        "\n封禁时长：" + Extensions.FormatTime(violations.ElementAt(i).duration) +
                        "\n违规时间：" + violations.ElementAt(i).violation_datetime +
                        "\n处理人：" + violations.ElementAt(i).issuer +
                        "\n违规编号：" + violations.ElementAt(i).refid);
                }
                result = resultString.ToString();
            }
            await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId, result, cmdInfo.MessageId);
        }
    }

    public class UnbanCommand : INormalCommand
    {
        public string Command => "/unban";

        public bool AdminChannelOnly => true;

        public int RequiredPermission => 2;

        public bool BotChannelRestricted => true;

        public async Task Execute(CommandInfo cmdInfo)
        {
            if (cmdInfo.Param.Count == 0)
            {
                await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
    "用法：/unban <用户ID>", cmdInfo.MessageId);
                return;
            }
            ExecutionRequest er = new()
            {
                Request = Request.Unban
            };
            er.Parameters.Add("userid", cmdInfo.Param[0]);
            foreach (var svr in Rg.Config.Servers)
            {
                string result = await svr.SendMsg(JsonConvert.SerializeObject(er));
                if (result == "Offline" || result == "Unknown")
                {
                    continue;
                }
                await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
"✅已解除封禁", cmdInfo.MessageId);
                return;
            }
            await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
"❌所有服务器均离线", cmdInfo.MessageId);
        }
    }

    public class MuteCommand : INormalCommand
    {
        public string Command => "/mute";

        public bool AdminChannelOnly => true;

        public int RequiredPermission => 2;

        public bool BotChannelRestricted => true;

        public async Task Execute(CommandInfo cmdInfo)
        {
            if (cmdInfo.Param.Count < 3)
            {
                await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
    "用法：/mute [服务器编号(如果执行SteamID封禁，可以不填)] <SteamID/数字ID> <时长>" +
    "【时长填写格式：纯数字默认单位为分，以h/H结尾为小时, d/D为天，m/M为月(30天), y/Y为年（不可复合）】", cmdInfo.MessageId);
                return;
            }
            ExecutionRequest er = new()
            {
                Request = Request.Mute
            };
            bool specified = cmdInfo.Param.Count == 3;
            if (!int.TryParse(cmdInfo.Param[specified ? 2 : 1], out int duration))
            {
                if (!int.TryParse(cmdInfo.Param[specified ? 2 : 1].Remove(cmdInfo.Param[specified ? 2 : 1].Length - 1, 1), out duration))
                {
                    await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
                    "请输入正确的时长", cmdInfo.MessageId);
                    return;
                }
                switch (cmdInfo.Param[specified ? 2 : 1].Last().ToString().ToLower())
                {
                    case "h": duration *= 60; break;
                    case "d": duration *= 1440; break;
                    case "m": duration *= 43200; break;
                    case "y": duration *= 525960; break;
                    default:
                        {
                            await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
                            "请输入正确的时长单位", cmdInfo.MessageId);
                            return;
                        }
                }
            }
            er.Parameters.Add("userid", cmdInfo.Param[specified ? 1 : 0]);
            er.Parameters.Add("minutes", duration);
            er.Parameters.Add("specified", specified);
            string msg = JsonConvert.SerializeObject(er);
            List<Task<string>> tasks = new();
            if (specified)
            {
                if (!int.TryParse(cmdInfo.Param[0], out int id))
                {
                    await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
                    "请输入正确的服务器编号", cmdInfo.MessageId);
                    return;
                }
                if (id > Rg.Config.Servers.Count)
                {
                    await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
                    "你要不要看看你有几个服务器", cmdInfo.MessageId);
                    return;
                }
                tasks.Add(Rg.Config.Servers[id - 1].SendMsg(msg));
            }
            else
            {
                Rg.Config.Servers.ForEach(x => tasks.Add(x.SendMsg(msg)));
            }
            var result = await Task.WhenAll(tasks.ToArray());
            for (int i = 0; i < result.Length; i++)
            {
                try
                {
                    if (result[i] == "Offline" || result[i] == "Unknown")
                    {
                        continue;
                    }
                    else
                    {
                        ExecutionResponse? rep = JsonConvert.DeserializeObject<ExecutionResponse>(result[i]);
                        if (rep == null)
                        {
                            continue;
                        }
                        if (rep.Success)
                        {
                            string nickname = (string)rep.Response["nickname"];
                            string userid = (string)rep.Response["userid"];
                            await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
                                $"成功！玩家【{nickname}】({userid}) 已被禁言 {Extensions.FormatTime(duration)}", cmdInfo.MessageId);
                            return;
                        }
                    }
                }
                catch (Exception e)
                {
                    Log.Error(e);
                    continue;
                }
            }
            if (specified)
            {
                await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
$"禁言失败！可能是指定ID对应玩家不存在", cmdInfo.MessageId);
            }
            else
            {
                er.Parameters["specified"] = true;
                msg = JsonConvert.SerializeObject(er);
                foreach (var svr in Rg.Config.Servers)
                {
                    string rsu = await svr.SendMsg(msg);
                    try
                    {
                        if (rsu == "Offline" || rsu == "Unknown")
                        {
                            continue;
                        }
                        else
                        {
                            ExecutionResponse? rep = JsonConvert.DeserializeObject<ExecutionResponse>(rsu);
                            if (rep == null)
                            {
                                continue;
                            }
                            if (rep.Success)
                            {
                                string nickname = (string)rep.Response["nickname"];
                                string userid = (string)rep.Response["userid"];
                                await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
                                    $"成功！玩家【{nickname}】({userid}) 已被禁言 {Extensions.FormatTime(duration)}", cmdInfo.MessageId);
                                return;
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        Log.Error(e);
                        continue;
                    }
                }
                await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
$"封禁失败！没有任何服务器返回一个禁言结果！", cmdInfo.MessageId);
            }
        }
    }

    public class UnmuteCommand : INormalCommand
    {
        public string Command => "/unmute";

        public bool AdminChannelOnly => true;

        public int RequiredPermission => 2;

        public bool BotChannelRestricted => true;

        public async Task Execute(CommandInfo cmdInfo)
        {
            if (cmdInfo.Param.Count == 0)
            {
                await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
    "用法：/unmute [服务器编号(如果执行SteamID解禁，可以不填)] <SteamID>", cmdInfo.MessageId);
                return;
            }
            ExecutionRequest er = new()
            {
                Request = Request.Unmute
            };
            bool specified = cmdInfo.Param.Count == 2;
            er.Parameters.Add("userid", cmdInfo.Param[specified ? 1 : 0]);
            string msg = JsonConvert.SerializeObject(er);
            List<Task<string>> tasks = new();
            if (specified)
            {
                if (!int.TryParse(cmdInfo.Param[0], out int id))
                {
                    await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
                    "请输入正确的服务器编号", cmdInfo.MessageId);
                    return;
                }
                if (id > Rg.Config.Servers.Count)
                {
                    await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
                    "你要不要看看你有几个服务器", cmdInfo.MessageId);
                    return;
                }
                tasks.Add(Rg.Config.Servers[id - 1].SendMsg(msg));
            }
            else
            {
                Rg.Config.Servers.ForEach(x => tasks.Add(x.SendMsg(msg)));
            }
            var result = await Task.WhenAll(tasks.ToArray());
            for (int i = 0; i < result.Length; i++)
            {
                try
                {
                    if (result[i] == "Offline" || result[i] == "Unknown")
                    {
                        continue;
                    }
                    else
                    {
                        ExecutionResponse? rep = JsonConvert.DeserializeObject<ExecutionResponse>(result[i]);
                        if (rep == null)
                        {
                            continue;
                        }
                        if (rep.Success)
                        {
                            string nickname = (string)rep.Response["nickname"];
                            string userid = (string)rep.Response["userid"];
                            await Rg.Api.GetMessageApi().SendTextMessageAsync(cmdInfo.ChannelId,
                                $"成功！玩家【{nickname}】({userid}) 已被解除禁言！", cmdInfo.MessageId);
                            return;
                        }
                    }
                }
                catch (Exception e)
                {
                    Log.Error(e);
                    continue;
                }
            }
        }
    }
}